package one.stand.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.wxpay.sdk.WXPayUtil;
import one.stand.code.RedisCode;
import one.stand.entity.OrderNoEntity;
import one.stand.entity.WxNoticeEntity;
import one.stand.entity.excel.OrdersExcelEntity;
import one.stand.enums.*;
import one.stand.model.*;
import one.stand.request.OrdersRequest;
import one.stand.response.OrdersResponse;
import one.stand.service.OrdersService;
import one.stand.service.WxMessageService;
import one.stand.util.AESUtil;
import one.stand.util.DateUtil;
import one.stand.util.ExportDataDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author
 */
@Service
@Transactional
public class OrdersServiceImpl extends PublicBaseService implements OrdersService {

    @Autowired
    protected WxMessageService wxMessageService;

    @Override
    public ResultModel selectOrdersInfo(OrdersRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        OrdersModel model = new OrdersModel();
        model.setOrderState(request.getOrderState());
        model.setCompanyId(request.getCId().intValue());
        model.setCreateTimes(request.getCreateTimes());
        model.setPayTimes(request.getPayTimes());
        List<OrdersModel> list = ordersMapper.getOrderList(model);
        if (list == null || list.size() <= 0) {
            return ResultModel.noData();
        }
        List<OrdersResponse> responseList = new ArrayList<>();
        list.forEach(obj -> responseList.add(convertOrders(obj)));
        PageInfo<OrdersResponse> pageInfo = new PageInfo<>(responseList);
        return ResultModel.success(pageInfo.getList());
    }

    @Override
    public ResultModel<Map<String, Object>> selectOrdersInfoPc(OrdersRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        OrdersModel model = new OrdersModel();
        model.setOrderState(request.getOrderState());
        model.setCompanyId(request.getCId().intValue());
        model.setCreateTimes(request.getCreateTimes());
        model.setPayTimes(request.getPayTimes());
        List<OrdersModel> list = ordersMapper.getOrderListPc(model);
        if (list == null || list.size() <= 0) {
            return ResultModel.noData();
        }
        List<OrdersResponse> responseList = new ArrayList<>();
        list.forEach(obj -> responseList.add(convertOrders(obj)));
        PageInfo<OrdersResponse> pageInfo = new PageInfo<>(responseList);
        Map<String, Object> map = new HashMap<>(1);
        map.put("pageInfo", pageInfo);
        return ResultModel.success(map);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultModel<ExportDataDTO<OrdersExcelEntity>> exportOrdersInfoPc(OrdersRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        OrdersModel model = new OrdersModel();
        model.setOrderState(request.getOrderState());
        model.setCompanyId(request.getCId().intValue());
        model.setCreateTimes(request.getCreateTimes());
        model.setPayTimes(request.getPayTimes());

        log.info("导出订单列表参数：{}", JSON.toJSONString(request));

        List<OrdersModel> list = ordersMapper.getOrderListPc(model);
        if (list == null || list.size() <= 0) {
            return ResultModel.noData();
        }

        List<OrdersExcelEntity> excelEntities = new ArrayList<>();
        list.forEach(ordersModel -> {
            {
                OrdersExcelEntity excelEntity = new OrdersExcelEntity();
                BeanUtils.copyProperties(ordersModel, excelEntity);
                excelEntity.setOrderPrice(ordersModel.getOrderPrice() / 100);
                excelEntity.setOrderState(OrderStateEnum.getMessage(ordersModel.getOrderState()));
                excelEntity.setAssembleId(ordersModel.getAssembleId() > 0 ? "拼团订单" : "个人订单");
                if(StringUtils.isNotEmpty(ordersModel.getNickeName())){
                    excelEntity.setNickeName(new String(java.util.Base64.getDecoder().decode(ordersModel.getNickeName().getBytes())));
                }
                excelEntities.add(excelEntity);
            }
        });
        ExportDataDTO exportDataDTO = new ExportDataDTO();
        exportDataDTO.setSheetName("订单列表");
        exportDataDTO.setFileName("订单列表");
        exportDataDTO.setTitle("订单列表");
        exportDataDTO.setDataList(excelEntities);
        return ResultModel.success(exportDataDTO);
    }



    private String formatDate(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return formatter.format(date);
    }


    /**
     * OrdersModel 转 OrdersResponse
     */
    private OrdersResponse convertOrders(OrdersModel model){
        OrdersResponse ordersResponse = new OrdersResponse();
        BeanUtils.copyProperties(model, ordersResponse, "ordersModelList", "deliveryTime", "killEndTime");
        if(StringUtils.isNotEmpty(model.getName())){
            ordersResponse.setNickeName(StringUtils.isBlank(model.getName()) ? "" : new String(Base64.getDecoder().decode(model.getName())));
            ordersResponse.setName(StringUtils.isBlank(model.getName()) ? "" : new String(Base64.getDecoder().decode(model.getName())));
        }
        if(StringUtils.isNotEmpty(model.getNickeName())){
            ordersResponse.setNickeName(StringUtils.isBlank(model.getNickeName()) ? "" : new String(Base64.getDecoder().decode(model.getNickeName())));
        }
        if (model.getDeliveryTime() != null) {
            ordersResponse.setDeliveryTimes(getSurplusDeliveryTime(model.getDeliveryTime()));
        }
        if(model.getKillEndTime() != null){
            ordersResponse.setKillEndTime(DateUtil.getDifferTime(model.getKillEndTime(), new Date()));
        }
        if(model.getOrdersModelList() != null){
            ordersResponse.setOrdersModelList(model.getOrdersModelList().stream().map(this::convertOrders).collect(Collectors.toList()));
        }
        return ordersResponse;
    }

    @Override
    public ResultModel<List<OrdersResponse>> getOrdersInfo(OrdersRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        OrdersModel model = new OrdersModel();
        model.setOrdersId(request.getOrdersId());
        model.setIds(new String[]{request.getOrdersId() + ""});
        List<OrdersModel> list = ordersMapper.getOrderInfo(model);
        if (list == null || list.size() <= 0) {
            return ResultModel.noData();
        }
        List<OrdersResponse> responseList = new ArrayList<>();
        list.forEach(obj -> responseList.add(convertOrders(obj)));
        return ResultModel.success(responseList);
    }

    @Override
    public ResultModel updateOrderState(OrdersRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        } else if (request.getOrdersId() == null) {
            return ResultModel.checkParamFail("ordersId为空");
        } else if (request.getOrderState() == null) {
            return ResultModel.checkParamFail("state为空");
        }
        OrdersModel model = new OrdersModel();
        model.setOrdersId(request.getOrdersId());
        model.setOrderState(request.getOrderState());
        model.setRefundRemark(request.getRefundRemark());
        if (OrderStateEnum.WAIT_RECEIVING.getCode().equals(request.getOrderState())) {
            model.setDeliveryTime(currentDate());
        }
        if (ordersMapper.updateOrderState(model) > 0) {
            // 微信推送 订单状态改变消息
            List<WxNoticeEntity> list = ordersMapper.getSendTemplateInfo(new OrdersModel() {{
                setType(1);
                setOrdersId(request.getOrdersId());
            }});
            list.forEach(entity -> {
                {
                    String[] fillData = {entity.getOrdersNo(), entity.getGoodsName(), getMoneyString(entity.getMoney()) + "元", OrderStateEnum.getMessage(request.getOrderState()), entity.getReceivePhone()};
                    wxMessageService.sendNewTemplate(entity.getUserOpenId(), entity.getUserFormId(), WxSubscribeEnums.ORDER_STATE_USER, fillData, LoginEnum.USER.getAccountType(), entity.getUserCompanyId());
                }
            });
            return ResultModel.success("操作成功");
        }
        return ResultModel.fail("操作失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultModel updateRefundState(OrdersRequest request) {
        log.info("订单退款参数：{}", JSON.toJSONString(request));
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        // 查询退款订单
        OrdersModel model = ordersMapper.selectPaymentInfo(request.getOrdersId());
        if (model == null) {
            log.info("商品信息异常", request.getOrdersId());
            return ResultModel.fail("商品信息异常");
        }
        if (model.getOrderState().equals(OrderStateEnum.REFUND_SUCCESS.getCode()) || model.getRefundState().equals(RefundStateEnum.REFUND_SUCCESS.getCode())) {
            log.info("请勿重新操作", model);
            return ResultModel.fail("请勿重新操作");
        }
        if (StringUtils.isBlank(model.getTradeNo()) || model.getTotalFee() == null) {
            log.info("订单信息异常，请联系客服", model);
            return ResultModel.fail("订单信息异常，请联系客服!");
        }
        // 确认退款
        if (RefundStateEnum.REFUND_SUCCESS.getCode().equals(request.getRefundState())) {
            try {
                String refundNo = getRefundNo();
                /**
                 *  微信退款操作：
                 */
                ResultModel resultModel = wxPayService.refund(model.getOutTradeNo(), refundNo, String.valueOf(model.getTotalFee()), String.valueOf(model.getPayPrice()), model.getRefundRemark(), model.getOrdersId());
                if (resultModel.isSuccess()) {
                    // 改变订单状态
                    backRefundTwo(request.getOrdersId(), model.getTotalFee(), model.getOutTradeNo(), refundNo);
                }
                return resultModel;
            } catch (Exception e) {
                log.info("修改订单退款状态[异常]", e);
            }
        } else {
            model = new OrdersModel();
            model.setOrdersId(request.getOrdersId());
            // 1未申请，2退款申请中，3退款成功
            model.setRefundState(request.getRefundState());
            int r = ordersMapper.updateByPrimaryKeySelective(model);
            if (r > 0) {
                return ResultModel.success("操作成功");
            }
        }
        return ResultModel.fail("操作失败");
    }

    @Autowired
    protected AESUtil aesUtil;

    /**
     * 微信退款回调 1
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String backRefund(String notifyData) {
        log.info("退款回调：{}", notifyData);
        Map<String, String> refundMap;
        try {
            // 初次解析回调参数
            refundMap = WXPayUtil.xmlToMap(notifyData);
            /** 退款成功*/
            if (refundMap != null) {
                if (refundMap.get("req_info") == null) {
                    log.info("回调异常，req_info为空：{}", refundMap.get("req_info"));
                    return wxPayService.fail();
                }
                // 根据redis中获取保存的微信商户支付key值
                String key = redisUtil.get(RedisCode.getWxKey(refundMap.get("nonce_str")));
                if (StringUtils.isBlank(key)) {
                    log.info("回调异常，key值为空：{}", refundMap.get("nonce_str"));
                    return wxPayService.fail();
                }
                // 解析退款req_info
                String stringXml = aesUtil.decryptData(refundMap.get("req_info"), key);
                if (stringXml == null) {
                    log.info("回调异常二次解析为空:{}", refundMap.get("req_info"));
                    return wxPayService.fail();
                }
                Map<String, String> notifyMap = WXPayUtil.xmlToMap(stringXml);
                if (notifyMap == null) {
                    log.info("微信退款回调二次解析结果异常 : {}", stringXml);
                    return wxPayService.fail();
                }
                // 退款订单编号
                String refundNo = notifyMap.get("out_refund_no");
                OrderNoEntity entity = redisUtil.get(RedisCode.getRefundOrderKey(refundNo));
                if (entity == null || entity.getOrdersId() == null) {
                    log.info("微信退款回调，redis中无支付退款订单号:{}", refundNo);
                    return wxPayService.fail();
                }
                OrdersModel model = ordersMapper.select(new OrdersModel() {{
                    setOrdersId(entity.getOrdersId());
                }});
                if (model == null || model.getOrderState().equals(OrderStateEnum.REFUND_SUCCESS.getCode())
                        || model.getRefundState().equals(RefundStateEnum.REFUND_SUCCESS.getCode())) {
                    log.info("订单状态信息异常：{}", JSON.toJSONString(model));
                    return wxPayService.fail();
                }
                // 删除redis里保存的订单信息
                redisUtil.remove(RedisCode.getRefundOrderKey(refundNo));
                if (PublicBaseService.SUCCESS.equals(notifyMap.get("refund_status"))) {
                    // 修改订单状态
                    backRefundTwo(model.getOrdersId(), entity.getMoney(), model.getOrdersNo(), refundNo);
                }
                return wxPayService.success();
            }
        } catch (Exception e) {
            log.info("微信退款回调验证错误[异常]", e);
        }
        return wxPayService.fail();
    }

    /**
     * 微信退款成功回调  2
     */
    public void backRefundTwo(Integer ordersId, Integer money, String ordersNo, String refundNo) {
        // 修改订单状态
        OrdersModel ordersModel = new OrdersModel();
        ordersModel.setOrderState(OrderStateEnum.REFUND_SUCCESS.getCode());
        ordersModel.setRefundState(RefundStateEnum.REFUND_SUCCESS.getCode());
        ordersModel.setOrdersId(ordersId);
        ordersMapper.updateByPrimaryKeySelective(ordersModel);
        // 微信推送模板 订单状态改变消息
        List<WxNoticeEntity> list = ordersMapper.getSendTemplateInfo(new OrdersModel() {{
            setType(2);
            setOrdersId(ordersId);
        }});
        if (list != null || list.size() > 0) {
            WxNoticeEntity wxNoticeEntity1 = list.get(0);
            String[] fillData = {wxNoticeEntity1.getOrdersNo(), wxNoticeEntity1.getGoodsName(), getMoneyString(money) + "元", OrderStateEnum.REFUND_SUCCESS.getMessage(), StringUtils.isEmpty(wxNoticeEntity1.getRefundRemark()) ? "订单退款" : wxNoticeEntity1.getRefundRemark()};
            wxMessageService.sendNewTemplate(wxNoticeEntity1.getUserOpenId(), wxNoticeEntity1.getUserFormId(), WxSubscribeEnums.ORDER_STATE_CRM, fillData, LoginEnum.CRM.getAccountType(), wxNoticeEntity1.getUserCompanyId());
        }
        // 添加退款记录信息
        RefundRecordModel refundRecordModel = new RefundRecordModel();
        refundRecordModel.setOrdersId(ordersId);
        refundRecordModel.setOrdersNo(ordersNo);
        refundRecordModel.setRefundNo(refundNo);
        refundRecordModel.setTotalFee(String.valueOf(money));
        refundRecordModel.setRefundFee(String.valueOf(money));
        refundRecordModel.setRefundStatus("SUCCESS");
        refundRecordModel.setCreateTime(currentDate());
        refundRecordMapper.insertSelective(refundRecordModel);
        // 拼团状态验证
        verificationAssemble(ordersId);
        return;
    }

    /**
     * 验证拼团状态
     *
     * @param ordersId
     */
    @Async("asyncServiceExecutor")
    public void verificationAssemble(Integer ordersId) {
        if (ordersId == null) {
            return;
        }
        List<OrdersModel> list = ordersMapper.verificationAssemble(ordersId);
        if (list == null || list.size() <= 0) {
            return;
        }
        int ii = 0;
        for (OrdersModel model : list) {
            if (OrderStateEnum.REFUND_SUCCESS.getCode().equals(model.getOrderState()) &&
                    RefundStateEnum.REFUND_SUCCESS.getCode().equals(model.getRefundState())) {
                ii++;
            }
        }
        if (ii == list.size()) {
            AssembleModel assembleModel = new AssembleModel();
            assembleModel.setState(4);
            assembleModel.setAssembleId(list.get(0).getAssembleId());
            assembleMapper.updateByPrimaryKeySelective(assembleModel);
        }
    }

    @Override
    public ResultModel delOrders(OrdersRequest request) {
        log.info("删除已过期的订单信息参数:{}", JSON.toJSONString(request));
        if (request == null) {
            return ResultModel.checkParamFail();
        } else if (request.getOrdersId() == null) {
            return ResultModel.checkParamFail("ordersId为空");
        }
        OrdersModel ordersModel = ordersMapper.selectByPrimaryKey(request.getOrdersId());
        if (ordersModel == null || ordersModel.getOrderState() != 0) {
            return ResultModel.fail("请选择已过期的商品订单信息~！");
        }
        OrdersModel model = new OrdersModel();
        model.setOrdersId(request.getOrdersId());
        model.setIsDel(1);
        ordersMapper.updateByPrimaryKeySelective(model);
        return ResultModel.success();
    }
}
